-
-
Notifications
You must be signed in to change notification settings - Fork 638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(hono/jwk): JWK Auth Middleware #3826
base: main
Are you sure you want to change the base?
Conversation
…yAlg fallback, add decodeHeaders utility - Added "kid" (Key ID) for TokenHeader - Fixed Jwt.sign() ignoring privateKey.alg - Renamed `alg` parameter to `KEYAlg` to differentiate between privateKey.alg - Added utility function `decodeHeaders` to decode only JWT headers
Hono JWK Middleware main features: - Ability to provide a list of public JWKs to the keys parameter as a simple javascript array [] - Ability to provide a URL in the jwks_uri parameter to fetch keys from + an optional RequestInit (useful for caching if your cloud provider has a modified fetch that supports it, or if you simply want to modify the request) - Ability to provide an async function that returns an array to the keys parameter instead of a direct array, so that it is possible to implement own custom caching layer without a separate middleware - Allows setting a keys directory for multi-key auth systems - Allows auth endpoints to be always updated with the Auth provider's public JWKs directory (often `.well-known/jwks.json`) which makes key rotations without disruptions possible Todo: - More tests.
Added /auth-keys-fn/* & /.well-known/jwks.json testing endpoints to the router.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3826 +/- ##
==========================================
- Coverage 91.71% 91.49% -0.22%
==========================================
Files 160 162 +2
Lines 10195 10355 +160
Branches 2885 3034 +149
==========================================
+ Hits 9350 9474 +124
- Misses 844 880 +36
Partials 1 1 ☔ View full report in Codecov by Sentry. |
Note that the test code I removed some commented out tests to give a clearer picture (Now at 307 lines of test code). But they did remind me—we need some signed cookie unit tests if we're gonna make sure to support everything in |
Hi @Beyondo Thanks! I'll check this later. |
@yusukebe No problem! I originally named the new interface Take your time! I'm using the fork temporarily, so no rush at all. |
Hello, I recently needed a JWK middleware for my projects, but I figured contributing it to hono has the potential to save me and others a lot of time.
Middleware Features:
options.keys
to a static array of public keysJsonWebKey[]
in code.options.keys
to an async function that returns aPromise<JsonWebKey[]>
for flexibilityoptions.jwks_uri
to fetch JWKs from a URI, after which it appends those fetched keys to providedkeys
if anyinit
parameter (only used forjwks_uri
)—useful if your host supports caching through custom init options.Added extra:
JwtHeaderRequiresKid
exception. Since the middleware requires presence of akid
field in the header in order to select the correct key.Jwt.verifyFromJwks
util function (batteries included).Addressed issues:
Other code changes:
JsonWebKey
to havekid?: string
(This is a standard: https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.4)kid?: string
to TokenHeaderJwt.sign(payload, privateKey, alg)
whereprivateKey.alg
was always ignored and onlyalg
parameter was considered.Suggestion: Removal of the default
'HS256'
value fromJwt.sign
and makealg
optional, so that if neitherprivateKey.alg
noralg
is defined, throw an error. My 'philosophy' for this is that it would be misleading for hono to display= 'HS256'
when the privateKey can internally have a different algorithm, such as when it is of typeJsonWebKey
orCryptoKey
(Though we only care aboutJsonWebKey
here). Makingalg
a "fallback" explicit parameter could be better.Example Usage:
Using
jwks_uri
Using
jwks_uri
and an optionalinit
Using
keys
from an arrayUsing
keys
as an async function (custom logic / caching)Tests:
I adapted a lot from JWT's own units tests to make sure some basic JWT validation exists, then added the actual validation for the JWK middleware's own functionality which is mostly: (1) getting keys through various methods, (2) selecting the appropriate JWK based on
kid
(without fully decoding the JWT—only the header), and then (3) verifying using the utilityJwt.verify
. Step 2 and 3 are done byJwt.verifyFromJwks
.JWK Middleware Test
Full Test
bun run format:fix && bun run lint:fix
to format the code (Done)Feel free to contribute more unit tests, extend and/or modify for the better.